package org.wu.framework.web.spring.request;

import org.wu.framework.lazy.orm.core.persistence.conf.LazyTableFieldEndpoint;
import org.wu.framework.web.request.LazyInterceptorRegistry;
import org.wu.framework.web.request.method.LazyHandlerMethodArgumentResolver;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.validation.MessageCodesResolver;
import org.springframework.validation.Validator;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.config.annotation.*;

import java.util.Comparator;
import java.util.List;

/**
 * @author Jia wei Wu
 */
@Slf4j
public class LazyWebMvcConfigurer implements WebMvcConfigurer {

    private final List<LazyHandlerMethodArgumentResolver<MethodParameter, NativeWebRequest>> lazyHandlerMethodArgumentResolvers;
    private final List<LazyInterceptorRegistry<Object>> lazyInterceptorRegistries;

    public LazyWebMvcConfigurer(List<LazyHandlerMethodArgumentResolver<MethodParameter, NativeWebRequest>> lazyHandlerMethodArgumentResolvers, List<LazyInterceptorRegistry<Object>> lazyInterceptorRegistries) {
        this.lazyHandlerMethodArgumentResolvers = lazyHandlerMethodArgumentResolvers;
        this.lazyInterceptorRegistries = lazyInterceptorRegistries;
    }


    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        List<LazyInterceptorRegistry<Object>> sortedList = lazyInterceptorRegistries.stream().sorted(Comparator.comparingInt(LazyInterceptorRegistry::order)).toList();
        for (LazyInterceptorRegistry<Object> lazyInterceptorRegistry : sortedList) {

            registry.addInterceptor(new HandlerInterceptor() {
                        @Override
                        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
                            return lazyInterceptorRegistry.preHandle(request, response, handler);
                        }


                        @Override
                        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
                            lazyInterceptorRegistry.postHandle(request, response, handler);
                        }

                        @Override
                        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
                            lazyInterceptorRegistry.afterCompletion(request, response, handler, ex);
                        }
                    }).
                    addPathPatterns(lazyInterceptorRegistry.addPathPatterns()).
                    excludePathPatterns(lazyInterceptorRegistry.excludePathPatterns());
        }
    }

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        for (LazyHandlerMethodArgumentResolver<MethodParameter, NativeWebRequest> lazyHandlerMethodArgumentResolver : lazyHandlerMethodArgumentResolvers) {
            HandlerMethodArgumentResolver handlerMethodArgumentResolver =
                    new HandlerMethodArgumentResolver() {

                        @Override
                        public boolean supportsParameter(MethodParameter parameter) {
                            return lazyHandlerMethodArgumentResolver.supportsParameter(parameter);
                        }

                        @Override
                        public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
                            return lazyHandlerMethodArgumentResolver.resolveArgument(parameter, webRequest);
                        }
                    };
            resolvers.addFirst(handlerMethodArgumentResolver);
        }
    }

    @Override
    public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers) {

    }

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    }

    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
    }

    @Override
    public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
    }

    @Override
    public void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
    }

    @Override
    public Validator getValidator() {
        return null;
    }

    @Override
    public MessageCodesResolver getMessageCodesResolver() {
        return null;
    }
}
